/**
 * 
 */
package edu.hitsz.cs.nlp.struct;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

import edu.hitsz.cs.nlp.struct.ConllSentence;
import edu.hitsz.cs.nlp.util.FeatureTemplate;



/**
 * CoNLL 2000 File
 * This is Conll2000 Shared Task's file format
 * 
 * @author lee
 */

public class ConllFile {
	
	public int sentenceNumber;
	public int unKnownThres=4;
	public Vector<ConllSentence> totalSentence;
	public Vector<String> resultSignal;
	
	public ConllFile(){
		sentenceNumber=0;	
		totalSentence=new Vector<ConllSentence>();
		resultSignal=new Vector<String>();
	}

	/**
	 * read training file
	 * @param trainName Name of the Input File
	 * @param size Number of inputing sentences: size=0 denotes all the sentences
	 */
	public void readTrainFile(String trainName, int size){
		if(size==0)
			size=100000;
		String trainFileName=trainName;
		File file = new File(trainFileName);
		BufferedReader reader = null;
		int stopsignal=0;
		try{
			reader = new BufferedReader(new FileReader(file));
			System.out.println("\nRead Training file successed:");
			String tempString=null;
			Vector<String> tempSentence=new Vector<String>();
			try{
				//��ȡ�ļ���ֱ���ļ�ĩβ
				while ((tempString = reader.readLine())!= null && stopsignal==0){
					tempSentence.add(tempString);
					//��ȡһ�����ӣ�ÿ�������ж����������ɣ�����֮����һ������
					tempString = reader.readLine();
					while (!(tempString.trim().equals(""))&&(tempString!=null)){
						tempSentence.add(tempString);
						tempString = reader.readLine();
						}
					//������ӣ��洢
					if (tempString!=null){
						//System.out.println("Have Read the "+sentenceNumber+"th Sentence;");
						if(sentenceNumber%1000==0)
							System.out.println("Have Read the "+sentenceNumber+"th Sentence;");
						if(sentenceNumber<size){
							//System.out.println("Have Read "+sentenceNumber+"th Sentences.");
							ConllSentence sentence=new ConllSentence();
							sentence.processTrain(tempSentence,tempSentence.size());
							//sentence.outputTrainSentence();
							totalSentence.add((ConllSentence)sentence.clone());
							sentenceNumber++;							
						}
						else
							stopsignal=1;
						tempSentence.clear();
					}
				}
				System.out.println("Have Read "+sentenceNumber+" Sentences.");
				try {
					reader.close();
					} 
				catch (IOException e) {
					e.printStackTrace();
					}
				}
			catch (FileNotFoundException e) {
				System.err.println(e);
				}
			}
		catch (IOException e){
			System.out.println("IOException: " + e);
			}
		}

	
	/**
	 * read test file
	 * @param path Directory of the input file
	 * @param trainName Name of the Input File
	 * @param size Number of inputing sentences: size=0 means all the sentences
	 */
	public void readTestFile(String testName, int size){
		if(size==0)
			size=100000;
		File file = new File(testName);
		BufferedReader reader = null;
		int stopsignal=0;
		try{
			reader = new BufferedReader(new FileReader(file));
			System.out.println("\nOpen Test File Successed. Reading");
			String tempString=null;
			Vector<String> tempSentence=new Vector<String>();
			try{
				//��ȡ�ļ���ֱ���ļ�ĩβ
				while ((tempString = reader.readLine()) != null && stopsignal==0){
					tempSentence.add(tempString);
					//��ȡһ�����ӣ�ÿ�������ж����������ɣ�����֮����һ������
					tempString = reader.readLine();
					while (!(tempString.trim().equals("")) &&(tempString!=null)){
						tempSentence.add(tempString);
						tempString = reader.readLine();
						}
					//������ӣ��洢
					if (tempString!=null){
						if(sentenceNumber%1000==0)
							System.out.println(sentenceNumber+"...");
						if(sentenceNumber<size){
							ConllSentence sentence=new ConllSentence();
							sentence.processTest(tempSentence,tempSentence.size());
							totalSentence.add((ConllSentence)sentence.clone());
							sentenceNumber++;
						}
						else
							stopsignal=1;
						tempSentence.clear();
					}
				}
				reader.close();				
				System.out.println("Reading "+sentenceNumber+" Sentences is done.");
			}
			catch (FileNotFoundException e) {
				System.err.println(e);
			}
		}
		catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
	
	/**
	 * add new sentence to file
	 * @param newSentence
	 */
	public void addSentence(ConllSentence newSentence){
		this.sentenceNumber++;
		this.totalSentence.add(newSentence);
	}
	
	/**
	 * add sentences of one file into this file
	 * @param newFile
	 */
	public void addFile(ConllFile newFile){
		this.sentenceNumber+=newFile.sentenceNumber;
		this.totalSentence.addAll(newFile.totalSentence);
	}
	
	/**
	 * Store File
	 * @param fileName
	 */
	public void storeFile(String fileName)
	{
		try{
			FileWriter outFileWriter=new FileWriter(fileName);
			for(int i=0;i<sentenceNumber;i++){	
				totalSentence.get(i).storeSentence(outFileWriter);
			}
			outFileWriter.close();
			System.out.println("\nStore train file has done!");
		}
		catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}

	/**
	 * Store sentences in reverse order. It operates like first storing the nth sentence, then n-1th, ... , final the first one.
	 * @param fileName
	 */
	public void storeReverseFile(String fileName)
	{
		try{
			FileWriter outFileWriter=new FileWriter(fileName);
			for(int i=sentenceNumber-1;i>=sentenceNumber;i--){	
				totalSentence.get(i).storeSentence(outFileWriter);
			}
			outFileWriter.close();
			System.out.println("\nStore train file has done!");
		}
		catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
	
	/**
	 * Store sentences in which the tokens are in reverse order,
	 * @param fileName
	 */
	public void storeFileWithReverseSentence(String fileName)
	{
		try{
			FileWriter outFileWriter=new FileWriter(fileName);
			for(int i=0;i<sentenceNumber;i++){
				totalSentence.get(i).storeReverseSentence(outFileWriter);
			}
			outFileWriter.close();
			System.out.println("\nStore train file has done!");
		}
		catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
	
	/**
	 * extract and store feature in file according to feature template
	 * @param newFile
	 * @param newTemplate
	 * @throws IOException
	 */
	public void extractAndStoreFeatures(FileWriter newFile, FeatureTemplate newTemplate) throws IOException{
		System.out.println("\nStore features in file:");
		int senNum=this.sentenceNumber;
		for(int i=0;i<senNum;i++){
			if(i%100==0)
				System.out.println(i+"...");
			this.totalSentence.get(i).extractAndStoreFeatures(newFile,newTemplate);			
		}
		
		System.out.println("Store features done in total "+senNum+" sentences.");
	}
	
	
	/**
	 * extract and store feature in file according to hand-crafted
	 * @param newFile
	 * @param newTemplate
	 * @throws IOException
	 */
	public void extractAndStoreFeatures(FileWriter newFile, String type) throws IOException{
		System.out.println("\nStore features in file:");
		int senNum=this.sentenceNumber;
		for(int i=0;i<senNum;i++){
			if(i%100==0)
				System.out.println(i+"...");
			this.totalSentence.get(i).extractAndStoreFeatures(newFile,type);			
		}
		
		System.out.println("Store features done in total "+senNum+" sentences.");
	}
	
	
	
	/**
	 * Store correct tags
	 * @param fileName
	 */
	public void storeSenResultFile(String fileName)
	{
		try{
			FileWriter outFileWriter=new FileWriter(fileName);
			System.out.println("\nStore test file in:");
			int i=0;
			for(;i<sentenceNumber;i++){
				if(i%1000==0)
					System.out.print(i+"...");
				totalSentence.get(i).storeSenResultSentence(outFileWriter);
			}
			System.out.print(i+".");
			outFileWriter.close();
			System.out.println("\nStore test file done!");			
		}catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
	
	
	
	/**
	 * Store predicted tags
	 * @param fileName
	 */
	public void storePredictFile(String fileName)
	{
		try{
			FileWriter outFileWriter=new FileWriter(fileName);
			System.out.println("\nStore test file in:");
			int i=0;
			for(;i<sentenceNumber;i++){
				if(i%1000==0)
					System.out.print(i+"...");
				totalSentence.get(i).storePredictSentence(outFileWriter);
			}
			System.out.print(i+".");
			outFileWriter.close();
			System.out.println("\nStore test file done!");			
		}catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
	
	/**
	 * Store the ith-best tags in k-best values
	 * @param fileName
	 * @param ith
	 */
	public void storePredictFile(String fileName, int ith)
	{
		String testFileName=fileName+"-"+Integer.toString(ith+1);
		try{
			FileWriter outFileWriter=new FileWriter(testFileName);
			System.out.println("\nStore test file in:");
			int i=0;
			for(;i<sentenceNumber;i++){
				if(i%1000==0)
					System.out.print(i+"...");
				totalSentence.get(i).storePredictSentence(outFileWriter, ith);
			}
			System.out.print(i+".");
			outFileWriter.close();
			System.out.println("\nStore test file done!");			
		}catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
	
	/**
	 * read result tags from imputing file
	 * @param path
	 * @param fileName
	 */
	public void readResultSignal(String fileName){
		resultSignal.clear();
		File file = new File(fileName);
		BufferedReader reader = null;
		try{
			reader = new BufferedReader(new FileReader(file));
			System.out.println("\nRead result signal file successed.");
			String tempString=null;
			try{
				//��ȡ�ļ���ֱ���ļ�ĩβ
				while ((tempString = reader.readLine())!= null){
					if (!(tempString.trim().equals(""))&&(tempString!=null)){						
						resultSignal.add(tempString.trim());
					}
				}
				try {
					reader.close();
					} 
				catch (IOException e) {
					e.printStackTrace();
					}
				}
			catch (FileNotFoundException e) {
				System.err.println(e);
				}
			}
		catch (IOException e){
			System.out.println("IOException: " + e);
			}
	}
		
	/**
	 * generate the result signal (correct tags) from the inputting sentences
	 *
	 */
	public void generateResultSignal(){
		for(int i=0;i<sentenceNumber;i++){
			int sentenceLen=totalSentence.get(i).sentenceLength;
			for(int j=0;j<sentenceLen;j++){
				if(!resultSignal.contains(totalSentence.get(i).senResultSignal.get(j))){
					resultSignal.add(totalSentence.get(i).senResultSignal.get(j));
				}
			}
		}		
	}
	
	/**
	 * Store result tags
	 * @param fileName
	 */
	public void storeResultSignal(String fileName){
		try{
			FileWriter outFileWriter=new FileWriter(fileName);
			int resultSignalNum=resultSignal.size();
			for(int i=0;i<resultSignalNum;i++){
				outFileWriter.write(resultSignal.get(i)+"\n");
			}
			outFileWriter.close();
			System.out.println("\nStore result Signal (Containing Tags) file done!");			
		}catch (IOException e){
			System.out.println("IOException: " + e);
		}
	}
		
		
	public void addEmptySentences(int n){
		for(int i=0;i<n;i++){
			ConllSentence newSen=new ConllSentence();
			this.addSentence(newSen);
		}
	}
	
	
	public void outputFile(){
		for(int i=0;i<sentenceNumber;i++)
			totalSentence.get(i).outputSentence();
	}
	

	
	/*
	 * print a vector of strings
	 */
	public void printVector(Vector<String> features){
		int len=features.size();
		System.out.println("\n"+Integer.toString(len));
		for(int i=0;i<len;i++){
			System.out.println(features.get(i));
		}
	}
	
		
//////////////////////////////////////////////////////////////////////////
		
	
	/**
	 * for program testing
	 */
	static void testRead(){
		ConllFile trainFile=new ConllFile();
		ConllFile testFile=new ConllFile();
		String trainName="/windows/F/experiments/joint/15-18w";
		String trainNameP=trainName+"-r";
		trainFile.readTrainFile(trainName, 0);
		trainFile.storeFileWithReverseSentence(trainNameP);
		//testFile.preProcessTestFile(path,devName,devNameP,0);
		//trainFile.outputTrainFile();
	}		
	
	public static void main(String[] args){
		testRead();
	}


}
